package top.codedance.iotp.tools.terminal.ui;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import top.codedance.iotp.common.constent.Command;
import top.codedance.iotp.tools.terminal.TerminalApplication;
import top.codedance.iotp.tools.terminal.bean.ComConnectParam;
import top.codedance.iotp.tools.terminal.comer.CallOwner;
import top.codedance.iotp.tools.terminal.comer.ComClient;

import javax.swing.*;
import javax.swing.tree.*;
import java.awt.*;
import java.net.URL;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;

/**
 *
 * @author xuedianfu
 */
public class OpcBrower extends javax.swing.JDialog implements CallOwner {
    private AddOpc opc;
    private WaitLoading waitLoading = new WaitLoading(this);
    private DefaultMutableTreeNode rootTn;
    private TreeModel tm;

    /**
     * Creates new form OpcBrower
     */
    public OpcBrower(AddOpc opc) {
        super(opc, true);
        this.opc = opc;
        initComponents();

        URL url = Thread.currentThread().getContextClassLoader().getResource("logo.gif");
        ImageIcon icon = new ImageIcon(url);
        setIconImage(icon.getImage());
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        setLocationRelativeTo(this.opc.getClientPluginTester().getShellFrame());
        setMinimumSize(new Dimension(500, 400));
        setResizable(true);
        setTitle("代码飞舞采控系统-OPC节点浏览器");

        initJTree();
    }

    public void setClientId(String id){
        jtf_clientId.setText(id);
    }

    private void initJTree(){
        rootTn = new DefaultMutableTreeNode("根");
        tm = new DefaultTreeModel(rootTn);
        this.jt_nodes.setModel(tm);
    }

    @Override
    public String getOwnerClassName() {
        return this.getClass().getTypeName();
    }

    /**
     * 展开所有树
     * @param tree
     * @param parent
     */
    private void expandTree(JTree tree, TreePath parent) {
        TreeNode node = (TreeNode) parent.getLastPathComponent();
        if (node.getChildCount() >= 0) {
            for (Enumeration<?> e = node.children(); e.hasMoreElements();) {
                TreeNode n = (TreeNode) e.nextElement();
                TreePath path = parent.pathByAddingChild(n);
                expandTree(tree, path);
            }
        }
        tree.expandPath(parent);
    }

    /**
     * 填充树
     * @param result
     * @param node
     */
    private void fillJTree(JSONObject result, DefaultMutableTreeNode node){
        Set<Map.Entry<String, Object>> entries = result.entrySet();
        for (Map.Entry<String, Object> entry : entries){
            DefaultMutableTreeNode cNode = new DefaultMutableTreeNode(entry.getKey());
            JSONObject value = (JSONObject)entry.getValue();
            if(value.size() > 0){
                fillJTree(value, cNode);
            }
            node.add(cNode);
        }
    }

    @Override
    public void appendResult(String data) {
        over();
        TerminalApplication.syslogInfo(data);
        if (data != null) {
            try{
                JSONObject result = JSON.parseObject(data);
                fillJTree(result, this.rootTn);
                this.jt_nodes.repaint();
                TreeNode root = (TreeNode) jt_nodes.getModel().getRoot();
                expandTree(jt_nodes, new TreePath(root));
            }catch (Exception e){
                TerminalApplication.syslogInfo(e.getMessage());
            }
        }
    }

    @Override
    public void appendError(String data) {
        over();
        if (data != null) {
            TerminalApplication.syslogInfo(data);
            JSONObject jsonObject = JSON.parseObject(data);
            JOptionPane.showMessageDialog(this.getRootPane(), "执行失败: " + jsonObject.getString("msg"));
        }
    }

    private void createComClient(String comName, String btl, String sjw, String tzw, String xyw){
        this.opc.cpt.sf.ccs.put(comName, new ComClient(this, new ComConnectParam(comName, Integer.parseInt(btl), Integer.parseInt(sjw), Integer.parseInt(tzw), Integer.parseInt(xyw))));
    }

    private void comSendCmd(String cmd){
        if(this.opc.cpt.currentConnectionParam == null || this.opc.cpt.currentConnectionParam.isEmpty()){
            JOptionPane.showMessageDialog(rootPane, "请选取连接配置。");
            return;
        }
        if(!this.opc.cpt.currentConnectionParam.containsKey("com") || this.opc.cpt.currentConnectionParam.getString("com").isEmpty()){
            JOptionPane.showMessageDialog(rootPane, "请选取Com口的连接配置。");
            return;
        }
        waiting();
        TerminalApplication.pool.submit(() -> {
            JSONObject com = this.opc.cpt.currentConnectionParam.getJSONObject("com");
            String comName = com.getString("value");
            String btl = this.opc.cpt.currentConnectionParam.getString("btl");
            String sjw = this.opc.cpt.currentConnectionParam.getString("sjw");
            String tzw = this.opc.cpt.currentConnectionParam.getString("tzw");
            String xyw = this.opc.cpt.currentConnectionParam.getString("xyw");
            if (!this.opc.cpt.sf.ccs.containsKey(comName)) {
                createComClient(comName, btl, sjw, tzw, xyw);
            }else{
                ComClient comClient = this.opc.cpt.sf.ccs.get(comName);
                comClient.setOwner(this);
            }
            JSONObject command = new JSONObject();
            command.put("cmd", cmd);
            ComClient comClient = this.opc.cpt.sf.ccs.get(comName);
            comClient.send(command.toJSONString());
        });
    }

    private void waiting(){
        waitLoading.open();
    }

    private void over(){
        if(waitLoading != null) {
            waitLoading.close();
        }
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        jt_nodes = new javax.swing.JTree();
        jb_brower = new javax.swing.JButton();
        jb_select = new javax.swing.JButton();
        jLabel1 = new javax.swing.JLabel();
        jtf_clientId = new javax.swing.JTextField();

        jt_nodes.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jt_nodesMouseClicked(evt);
            }
        });
        jScrollPane1.setViewportView(jt_nodes);

        jb_brower.setText("获取根节点");
        jb_brower.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jb_browerActionPerformed(evt);
            }
        });

        jb_select.setText("选用当前节点");
        jb_select.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jb_selectActionPerformed(evt);
            }
        });

        jLabel1.setText("Client id：");

        jtf_clientId.setText("0");
        jtf_clientId.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyTyped(java.awt.event.KeyEvent evt) {
                jtf_clientIdKeyTyped(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 698, Short.MAX_VALUE)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jLabel1)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jtf_clientId, javax.swing.GroupLayout.PREFERRED_SIZE, 142, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(18, 18, 18)
                        .addComponent(jb_brower)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jb_select)
                        .addGap(0, 0, Short.MAX_VALUE)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jb_brower)
                    .addComponent(jb_select)
                    .addComponent(jLabel1)
                    .addComponent(jtf_clientId, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jScrollPane1)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void jb_browerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jb_browerActionPerformed
        if(jtf_clientId.getText().isEmpty()){
            JOptionPane.showMessageDialog(rootPane, "Client ID 不能为空, 必须为无符号整数，且在客户端配置中存在。");
            return;
        }
        initJTree();
        JSONObject commandParams = new JSONObject();
        commandParams.put("plugin", Command.OPC_COMMAND);
        JSONObject clientJo = new JSONObject();
        clientJo.put("id", Integer.valueOf(jtf_clientId.getText()));
        clientJo.put("data", new JSONObject());
        commandParams.put("client", clientJo);
        commandParams.put("runner", this.opc.cpt.RUNNER_TYPE);
        comSendCmd(commandParams.toJSONString());
    }//GEN-LAST:event_jb_browerActionPerformed

    private void jb_selectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jb_selectActionPerformed
        TreePath selectionPath = jt_nodes.getSelectionPath();
        Object[] path = selectionPath.getPath();
        if(path.length <= 0){
            JOptionPane.showMessageDialog(rootPane, "请选取一个节点。");
            return;
        }
        String tag = path[path.length - 1].toString();
        TerminalApplication.syslogInfo("当前选中标签：" + tag);
        this.opc.setTag(tag);
        setVisible(false);
    }//GEN-LAST:event_jb_selectActionPerformed

    private void jt_nodesMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jt_nodesMouseClicked
        if (evt.getClickCount() == 2) {
            jb_selectActionPerformed(null);
        }
    }//GEN-LAST:event_jt_nodesMouseClicked

    private void jtf_clientIdKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_jtf_clientIdKeyTyped
        JTextField jtf = (JTextField)evt.getSource();
        if (!TerminalApplication.numbers.contains(evt.getKeyChar())) {
            evt.consume();
        }
        try{
            Integer.parseInt(jtf.getText());
            if(jtf.getText().startsWith("0")){
                jtf.setText(jtf.getText().replaceAll("^0+", ""));
            }
        }catch (Exception e){
            jtf.setText("0");
        }
    }//GEN-LAST:event_jtf_clientIdKeyTyped

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JLabel jLabel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JButton jb_brower;
    private javax.swing.JButton jb_select;
    private javax.swing.JTree jt_nodes;
    private javax.swing.JTextField jtf_clientId;
    // End of variables declaration//GEN-END:variables
}
